package dohmh.yelp.utilities;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;

import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.XMLEvent;

import dohmh.yelp.dataobjects.Business;
import dohmh.yelp.dataobjects.Review;

public class XMLFeedParser {
	private XMLEvent _event;
	private String _feedFile;
	private FileInputStream _fileInputStream = null;
	private XMLEventReader _xmlEventReader = null;

	public XMLFeedParser(String feedFile, String encoding) throws FileNotFoundException, XMLStreamException{
		_feedFile = feedFile;
		_fileInputStream = new FileInputStream(_feedFile);
		_xmlEventReader = XMLInputFactory.newInstance().createXMLEventReader(_fileInputStream, encoding);
	}

	public void close(){
		if (_xmlEventReader != null){
			try {
				_xmlEventReader.close();
			} catch (XMLStreamException e) {
				e.printStackTrace();
			}
			finally {
				if (_fileInputStream != null){
					try {
						_fileInputStream.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}

	public Business getBusiness() throws XMLStreamException{
		Business b = new Business();
		try {
			while (_xmlEventReader.hasNext()){
				_event = _xmlEventReader.nextEvent();
				if (_event.isStartElement()){
					String tagName = _event.asStartElement().getName().getLocalPart();
					if (tagName.equals("id")){
						b.setYelpId(_xmlEventReader.getElementText());
					}
					else if (tagName.equals("name")){ 
						b.setName(_xmlEventReader.getElementText());
					}
					else if (tagName.equals("address1")){
						b.setAddress(_xmlEventReader.getElementText());
					}
					else if (tagName.equals("city")){
						b.setCity(_xmlEventReader.getElementText());
					}
					else if (tagName.equals("state")){
						b.setState(_xmlEventReader.getElementText());
					}
					else if (tagName.equals("zipcode")){
						b.setZipCode(_xmlEventReader.getElementText());
					}
					else if (tagName.equals("category")){
						b.setCategory(_xmlEventReader.getElementText());
					}
					else if (tagName.equals("url")){
						b.setUrl(_xmlEventReader.getElementText());
					}
					else if (tagName.equals("reviews")){
						while (_xmlEventReader.hasNext()){
							_event = _xmlEventReader.nextEvent();
							if (_event.isStartElement() && _event.asStartElement().getName().getLocalPart().equals("review")){
								b.addReview(getReview());
							}
							else if (_event.isEndElement() && _event.asEndElement().getName().getLocalPart().equals("reviews")){
								break;
							}
						}
					}
				}
				else if (_event.isEndElement() && _event.asEndElement().getName().getLocalPart().equals("business")){
					break;
				}
			}
		} catch (XMLStreamException e){
			throw e;
		}
		return b;
	}

	public Review getReview() throws XMLStreamException{
		Review r = new Review();
		try {
			while (_xmlEventReader.hasNext()){
				_event = _xmlEventReader.nextEvent();
				if (_event.isStartElement()){
					String tagName = _event.asStartElement().getName().getLocalPart();
					if (tagName.equals("id")){
						r.setYelpId(_xmlEventReader.getElementText());
					}
					else if (tagName.equals("url")){
						r.setUrl(_xmlEventReader.getElementText());
					}
					else if (tagName.equals("member")){
						r.setMember(_xmlEventReader.getElementText());
					}
					else if (tagName.equals("rating")){
						r.setRating(Double.parseDouble(_xmlEventReader.getElementText()));
					}
					else if (tagName.equals("text")){
						r.setText(_xmlEventReader.getElementText().replace("<br />", "\n"));
					}
					else if (tagName.equals("time_created")){
						SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
						try{
							r.setTimeCreated(df.parse(_xmlEventReader.getElementText()));
						} catch (ParseException e){
							r.setTimeCreated(null);
						}
					}
				}
				else if (_event.isEndElement() && _event.asEndElement().getName().getLocalPart().equals("review")){
					break;
				}
			}
		} catch (XMLStreamException e){
			if (r.getYelpId() != null){
				System.out.println(r.getYelpId());
			}
			throw e;
		}
		return r;
	}

	public Boolean hasBusinesses() throws XMLStreamException{
		while (_xmlEventReader.hasNext()){
			_event = _xmlEventReader.nextEvent();
			if (_event.isStartElement() && _event.asStartElement().getName().getLocalPart().equals("business")){
				return true;
			}
		}
		return false;
	}

	public Boolean hasReviews() throws XMLStreamException{
		while (_xmlEventReader.hasNext()){
			_event = _xmlEventReader.nextEvent();
			if (_event.isStartElement() && _event.asStartElement().getName().getLocalPart().equals("review")){
				return true;
			}
		}
		return false;
	}
}
